#include <GeoIPCity.h>
#include <GeoIP.h>
#include <stdio.h>
#include "geoip.h"

#include <curl/curl.h>
#include <curl/easy.h>

#include <string>
#include <vector>
#include <iostream>

using namespace std;


static GeoIP *gi[4] = {};

static const char *searchPath[] = {
	"/usr/share/GeoIP/GeoIPCity.dat",
	"/usr/share/GeoIP/GeoLiteCity.dat",
	"/usr/share/GeoIP/GeoIP.dat",
	NULL
};

int close_geoip()
{
	int i;
	int ret = 0;
	for(i=0;searchPath[i];i++) {
		if(gi[i])
			GeoIP_delete(gi[i]);
	}
	return ret;
}

int init_geoip()
{
	int i;
	int ret = 0;
	for(i=0;searchPath[i];i++) {
		//fprintf(stderr, "Loading %s\n", searchPath[i]);
		gi[i] = GeoIP_open(searchPath[i], GEOIP_INDEX_CACHE);
	}
	return ret;
}

int getLatLongByIp(const char *ip, float *lat, float *lon)
{
	int i;
	int ret = 0;

	for(i=0;searchPath[i];i++) {
		if(gi[i]) {
			GeoIPRecord * gir;
			//fprintf(stderr, "Looking ip: %s\n", ip);
			gir = GeoIP_record_by_name(gi[i], ip);
			if(gir != NULL) {
				//fprintf(stderr, "Latitude: %f Longitude: %f\n", gir->latitude, gir->longitude);
				*lat = gir->latitude;
				*lon = gir->longitude;
				ret = 1;
				GeoIPRecord_delete(gir);
				break;
			}
		}
	}

	return ret;	
}

static size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp)
{
	unsigned int i;
	const char *b = (char *)buffer;
	std::string *str = (std::string *) userp;

	for(i=0;i<(size * nmemb);i++) {
		char tmp[2];
		tmp[0] = b[i];
		tmp[1]='\0';

		str->append(tmp);
	}
	return i;
}

void Tokenize(const string& str,
		vector<string>& tokens,
		const string& delimiters = " ")
{
	// Skip delimiters at beginning.
	string::size_type lastPos = str.find_first_not_of(delimiters, 0);
	// Find first "non-delimiter".
	string::size_type pos     = str.find_first_of(delimiters, lastPos);

	while (string::npos != pos || string::npos != lastPos)
	{
		// Found a token, add it to the vector.
		tokens.push_back(str.substr(lastPos, pos - lastPos));
		// Skip delimiters.  Note the "not_of"
		lastPos = str.find_first_not_of(delimiters, pos);
		// Find next "non-delimiter"
		pos = str.find_first_of(delimiters, lastPos);
	}
}



int getLatLongByIpWeb(const char *ip, const char *license, float *lat, float *lon)
{
	int ret = 0;
	CURL *c = curl_easy_init();
	std::string response;
	std::string query;
	vector<string> fields;

        curl_easy_setopt(c, CURLOPT_NOPROGRESS, 1);
        curl_easy_setopt(c, CURLOPT_URL, "http://geoip1.maxmind.com/f");

        curl_easy_setopt(c, CURLOPT_AUTOREFERER, 1);
        curl_easy_setopt(c, CURLOPT_FOLLOWLOCATION, 1);
#ifdef CURLOPT_POST301
        curl_easy_setopt(c, CURLOPT_POST301, 1);
#endif
        curl_easy_setopt(c, CURLOPT_MAXREDIRS, 5);

        curl_easy_setopt(c, CURLOPT_POST, 1);

        curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, write_data);
        curl_easy_setopt(c, CURLOPT_WRITEDATA, &response);

        query.append("i=").append(ip);
	if(license) {
		query.append("&l=").append(license);
	}

        curl_easy_setopt(c, CURLOPT_POSTFIELDS, query.c_str());

        curl_easy_perform(c);

//	cout << response << endl;

	Tokenize(response, fields, ",");
//        my ($country 0, $region 1, $city 2, $postal 3, $lat 4, $lon 5, $metro_code 6,
//        	$area_code 7, $isp 8 , $org 9 , $err 10) = $csv_parser->fields();

	*lat = atof(fields[3].c_str());
	*lon = atof(fields[4].c_str());

	curl_easy_cleanup(c);
	return ret;	
}
